package com.blic.utils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
 


@Component
public final class WeixinUtil {
	private static Logger log = LoggerFactory.getLogger("WX-OAUTH-LOG");

 

	/*****
	 * 替换token
	 * 
	 * @param url
	 * @param token
	 * @return
	 */
	public final static String replaceToken(String url, String token) {
	url = url.replace("ACCESS_TOKEN", token);
		return url;
	}

	/**
	 * 发起https请求并获取结果
	 * 
	 * @param token
	 *            Access_Token
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式（GET、POST）
	 * @param outputStr
	 *            提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public final static JSONObject httpRequest(String requestUrl, String token,
			String requestMethod, String outputStr) {
		if (!StringUtils.isEmpty(token)) {
			requestUrl = replaceToken(requestUrl, token);
		}
		return httpRequest(requestUrl, requestMethod, outputStr, 1);
	}

	/******
	 * 处理返回值
	 * 
	 * @param jsonObject
	 * @return
	 */
	/*public final static ResultProxy getResultProxy(JSONObject jsonObject) {
		ResultProxy resultProxy = new ResultProxy();
		resultProxy.setCode(jsonObject.getInteger("errcode"));
		resultProxy.setMessage(jsonObject.getString("errmsg"));
		return resultProxy;
	}*/

	/**
	 * 发起https请求并获取结果
	 * 
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式（GET、POST）
	 * @param outputStr
	 *            提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public final static JSONObject httpRequest(String requestUrl,
			String requestMethod, String outputStr, Integer cnt) {
		JSONObject jsonObject = null;
		HttpsURLConnection httpUrlConn = null;
		OutputStream outputStream = null;
		InputStream inputStream = null;
		InputStreamReader inputStreamReader = null;
		BufferedReader bufferedReader = null;
		try {
			// 1.创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 2.从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(requestUrl);
			httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);
			// 3.打开读写属性，默认均为false,Post请求不能使用缓存
			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			httpUrlConn.setInstanceFollowRedirects(true);
			httpUrlConn.setRequestProperty("Content-Type",
					"text/plain; charset=utf-8");
			// 4.设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);
			if ("GET".equalsIgnoreCase(requestMethod)) {
				httpUrlConn.connect();
			} else {
				httpUrlConn.setRequestProperty("Content-Type",
						"application/x-www-form-urlencoded");
				httpUrlConn.connect();
			}
			// 5.当有数据需要提交时
			if (null != outputStr) {
				outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.flush();
				outputStream.close();
			}

			// 6.将返回的输入流转换成字符串,后及时关闭资源
			inputStream = httpUrlConn.getInputStream();
			inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
			bufferedReader = new BufferedReader(inputStreamReader);
			// 7.接受返回结果
			StringBuffer buffer = new StringBuffer();
			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			Integer statusCode = httpUrlConn.getResponseCode();
			if (statusCode == 200) {
				jsonObject = JSONObject.parseObject(buffer.toString());
			} else {
				jsonObject = new JSONObject();
				jsonObject.put("errcode", 40001);
			}
			Object msgcode = jsonObject.get("errcode");
			if (msgcode != null) {
				log.info("wx2:statusCode|" + statusCode + "|url|" + requestUrl
						+ "|error|" + msgcode + "|" + jsonObject.get("errmsg"));
				// ex：token失效，重新生成
				if ("42001".equals(msgcode.toString())
						|| "40001".equals(msgcode.toString())
						|| "-1".equals(msgcode.toString())) {
					// 睡眠3秒，二次请求
					Integer newtoken = //myTokenUtil.nullOR42001CurAccessTokenStr();
					//Thread.sleep(5L);
					cnt = cnt != null ? cnt : 1;
					if (0 < cnt) {
						// 重复请求次数
						cnt -= 1;
						int index = requestUrl.indexOf("access_token=");
						int index2 = requestUrl.indexOf("&", index);
						requestUrl = requestUrl.substring(0, index + 13)
								+ newtoken
								+ (index2 == -1 ? "" : requestUrl
										.substring(index2));
						jsonObject = httpRequest(requestUrl, requestMethod,
								outputStr, cnt);
					}
				}
			} else {
				log.info("wx1:statusCode|" + statusCode + "|url|" + requestUrl
						+ "|jsonObject|" + jsonObject != null ? jsonObject
						.toJSONString() : null);
			}
		} catch (Exception e) {
			log.error("wx:https1|request|" + requestUrl + "|error:" + e);
		} finally {
			// 8.资源释放
			try {
				if (httpUrlConn != null) {
					httpUrlConn.disconnect();
				}
				if (outputStream != null) {
					outputStream.close();
				}
				if (inputStream != null) {
					inputStream.close();
				}
				if (inputStreamReader != null) {
					inputStreamReader.close();
				}
				if (bufferedReader != null) {
					bufferedReader.close();
				}
			} catch (Exception e) {
				log.error("wx:close|request|" + requestUrl + "|error:" + e);
			}
		}
		return jsonObject;
	}
	
	/**
	 * 
	* @Title: singleHttpRequest  
	* @Description: 单次请求url
	* @param @param requestUrl
	* @param @param requestMethod
	* @param @param outputStr
	* @param @param cnt
	* @param @return    设定文件  
	* @return JSONObject    返回类型  
	* @throws
	 */
	public final static JSONObject singleHttpRequest(String requestUrl,
			String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		HttpsURLConnection httpUrlConn = null;
		OutputStream outputStream = null;
		InputStream inputStream = null;
		InputStreamReader inputStreamReader = null;
		BufferedReader bufferedReader = null;
		try {
			// 1.创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 2.从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(requestUrl);
			httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);
			// 3.打开读写属性，默认均为false,Post请求不能使用缓存
			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			httpUrlConn.setInstanceFollowRedirects(true);
			httpUrlConn.setRequestProperty("Content-Type",
					"text/plain; charset=utf-8");
			// 4.设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);
			if ("GET".equalsIgnoreCase(requestMethod)) {
				httpUrlConn.connect();
			} else {
				httpUrlConn.setRequestProperty("Content-Type",
						"application/x-www-form-urlencoded");
				httpUrlConn.connect();
			}
			// 5.当有数据需要提交时
			if (null != outputStr) {
				outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.flush();
				outputStream.close();
			}

			// 6.将返回的输入流转换成字符串,后及时关闭资源
			inputStream = httpUrlConn.getInputStream();
			inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
			bufferedReader = new BufferedReader(inputStreamReader);
			// 7.接受返回结果
			StringBuffer buffer = new StringBuffer();
			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			Integer statusCode = httpUrlConn.getResponseCode();
			if (statusCode == 200) {
				jsonObject = JSONObject.parseObject(buffer.toString());
			} else {
				jsonObject = new JSONObject();
				jsonObject.put("errcode", 40001);
			}
			log.info("singleHttpRequest:statusCode|" + statusCode + "|url|" + requestUrl
						+ "|jsonObject|" + jsonObject != null ? jsonObject
						.toJSONString() : null);
		
		} catch (Exception e) {
			log.error("singleHttpRequest:https1|request|" + requestUrl + "|error:" + e);
		} finally {
			// 8.资源释放
			try {
				if (httpUrlConn != null) {
					httpUrlConn.disconnect();
				}
				if (outputStream != null) {
					outputStream.close();
				}
				if (inputStream != null) {
					inputStream.close();
				}
				if (inputStreamReader != null) {
					inputStreamReader.close();
				}
				if (bufferedReader != null) {
					bufferedReader.close();
				}
			} catch (Exception e) {
				log.error("singleHttpRequest:close|request|" + requestUrl + "|error:" + e);
			}
		}
		return jsonObject;
	}

}
